<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>xmake</title>
  <link rel="icon" href="/assets/img/favicon.ico">
  <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
  <meta name="description" content="Description">
  <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
  <link href="//cdn.jsdelivr.net/npm/github-markdown-css@4.0.0/github-markdown.min.css" rel="stylesheet">
  <style>
	.markdown-body {
		box-sizing: border-box;
		min-width: 200px;
		max-width: 980px;
		margin: 0 auto;
		padding: 45px;
	}

	@media (max-width: 767px) {
		.markdown-body {
			padding: 15px;
		}
	}
  </style>
</head>
<body>
<article class="markdown-body">
<h4>This is a mirror page, please see the original page: </h4><a href="https://xmake.io/#/zh-cn/manual/configuration_option">https://xmake.io/#/zh-cn/manual/configuration_option</a>
</br>
    <script async type="text/javascript" src="//cdn.carbonads.com/carbon.js?serve=CE7I52QU&placement=xmakeio" id="_carbonads_js"></script>
<style>
#carbonads {
  font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, Oxygen-Sans, Ubuntu,
  Cantarell, "Helvetica Neue", Helvetica, Arial, sans-serif;
}

#carbonads {
  display: flex;
  max-width: 330px;
  background-color: hsl(0, 0%, 98%);
  box-shadow: 0 1px 4px 1px hsla(0, 0%, 0%, .1);
}

#carbonads a {
  color: inherit;
  text-decoration: none;
}

#carbonads a:hover {
  color: inherit;
}

#carbonads span {
  position: relative;
  display: block;
  overflow: hidden;
}

#carbonads .carbon-wrap {
  display: flex;
}

.carbon-img {
  display: block;
  margin: 0;
  line-height: 1;
}

.carbon-img img {
  display: block;
}

.carbon-text {
  font-size: 13px;
  padding: 10px;
  line-height: 1.5;
  text-align: left;
}

.carbon-poweredby {
  display: block;
  padding: 8px 10px;
  background: repeating-linear-gradient(-45deg, transparent, transparent 5px, hsla(0, 0%, 0%, .025) 5px, hsla(0, 0%, 0%, .025) 10px) hsla(203, 11%, 95%, .4);
  text-align: center;
  text-transform: uppercase;
  letter-spacing: .5px;
  font-weight: 600;
  font-size: 9px;
  line-height: 1;
}
</style>
    <p>定义和设置选项开关，每个<code>option</code>对应一个选项，可用于自定义编译配置选项、开关设置。</p>
<p><p class="tip"><br>除了<code>target</code>以外的所有域接口，例如<code>option</code>，<code>task</code>等的接口，默认不能放置在外面的全局作用域中的（除非部分跟target共用的接口除外）。<br>如果要设置值影响所有<code>option</code>，<code>task</code>等选项，可以通过匿名全局域来设置。<br></p>

</p>
<p>例如：</p>
<pre><code class="lang-lua">-- 进入option的匿名全局域，里面的设置会同时影响test和test2选项
option()
    add_defines("DEBUG")

option("test")
    -- ...
    -- 尽量保持缩进，因为这个之后的所有设置，都是针对test选项的

option("test2")
    -- ...
</code></pre>
<p>!> <code>option</code>域是可以重复进入来实现分离设置的，如果要显示离开当前选项的作用域设置，可以手动调用<a href="#option_end">option_end</a>接口。</p>
<h3 id="option">option</h3>
<h4 id="">定义选项</h4>
<p>定义和设置选项开关，可用于自定义编译配置选项、开关设置。</p>
<p>例如，定义一个是否启用test的选项：</p>
<pre><code class="lang-lua">option("test")
    set_default(false)
    set_showmenu(true)
    add_defines("TEST")
</code></pre>
<p>然后关联到指定的target中去：</p>
<pre><code class="lang-lua">target("demo")
    add_options("test")
</code></pre>
<p>这样，一个选项就算定义好了，如果这个选项被启用，那么编译这个target的时候，就会自动加上<code>-DTEST</code>的宏定义。</p>
<pre><code class="lang-lua"># 手动启用这个选项
$ xmake f --test=y
$ xmake
</code></pre>
<h3 id="option_end">option_end</h3>
<h4 id="">结束定义选项</h4>
<p>这是一个可选api，显示离开选项作用域，用法和<a href="/mirror/zh-cn/manual/project_target.html#target_end">target_end</a>类似。</p>
<h3 id="optionadd_deps">option:add_deps</h3>
<h4 id="">添加选项依赖</h4>
<p>通过设置依赖，可以调整选项的检测顺序，一般用于<a href="#optionon_check">on_check</a>等检测脚本的调用时机。</p>
<pre><code class="lang-lua">option("small")
    set_default(true)
    on_check(function (option)
        -- ...
    end)

option("test")
    add_deps("small")
    set_default(true)
    after_check(function (option)
        if option:dep("small"):enabled() then
            option:enable(false)
        end
    end)
</code></pre>
<p>当依赖的small选项检测完成后，通过判断small选项的状态，来控制test的选项状态。</p>
<p>!> 由于 on_check 只有在没有设置 default 值的情况下才会被执行，因此如果设置了 default 值，那么可以在 after_check 阶段处理自定义逻辑。</p>
<h3 id="optionbefore_check">option:before_check</h3>
<h4 id="">选项检测之前执行此脚本</h4>
<p>例如：在检测之前，通过<a href="#detect-find_package">find_package</a>来查找包，将<code>links</code>, <code>includedirs</code>和<code>linkdirs</code>等信息添加到option中去，<br>然后开始选项检测，通过后就会自动链接到target上。</p>
<pre><code class="lang-lua">option("zlib")
    before_check(function (option)
        import("lib.detect.find_package")
        option:add(find_package("zlib"))
    end)
</code></pre>
<h3 id="optionon_check">option:on_check</h3>
<h4 id="">自定义选项检测脚本</h4>
<p>此脚本会覆盖内置的选项检测逻辑。</p>
<pre><code class="lang-lua">option("test")
    add_deps("small")
    on_check(function (option)
        option:enable(true)
    end)
</code></pre>
<p>!> 仅仅在 <code>set_default</code> 没有被设置的情况下，才会执行 <code>on_check</code> 进行自定义的选项检测脚本。</p>
<h3 id="optionafter_check">option:after_check</h3>
<h4 id="">选项检测之后执行此脚本</h4>
<p>在选项检测完成后，执行此脚本做一些后期处理，也可以在此时重新禁用选项：</p>
<pre><code class="lang-lua">option("test")
    add_deps("small")
    add_links("pthread")
    after_check(function (option)
        option:enable(false)
    end)
</code></pre>
<h3 id="optionset_values">option:set_values</h3>
<h4 id="">设置选项值列表</h4>
<p>仅用于<code>xmake f --menu</code>的图形菜单配置时，提供选项值列表供用户快速选择使用，例如：</p>
<pre><code class="lang-lua">option("test")
    set_default("b")
    set_showmenu(true)
    set_values("a", "b", "c")
</code></pre>
<p>效果图如下：</p>
<p><img src="/assets/img/manual/option_set_values.png" width="60%" /></p>
<h3 id="optionset_default">option:set_default</h3>
<h4 id="">设置选项默认值</h4>
<p>在没有通过<code>xmake f --option=[y|n}</code>等命令修改选项值的时候，这个选项本身也是有个默认值的，可以通过这个接口来设置：</p>
<pre><code class="lang-lua">option("test")
    -- 默认禁用这个选项
    set_default(false)
</code></pre>
<p>选项的值不仅支持boolean类型，也可以是字符串类型，例如：</p>
<pre><code class="lang-lua">option("test")
    set_default("value")
</code></pre>
<table>
<thead>
<tr>
<th>值类型</th>
<th>描述</th>
<th>配置</th>
</tr>
</thead>
<tbody>
<tr>
<td>boolean</td>
<td>一般用作参数开关，值范围：<code>true/false</code></td>
<td><code>xmake f --optionname=[y/n/yes/no/true/false]</code></td>
</tr>
<tr>
<td>string</td>
<td>可以是任意字符串，一般用于模式判断</td>
<td><code>xmake f --optionname=value</code></td>
</tr>
</tbody>
</table>
<p>如果是<code>boolean</code>值的选项，可以通过<a href="/mirror/zh-cn/manual/conditions.html#has_config">has_config</a>来进行判断，选项是否被启用。</p>
<p>如果是<code>string</code>类型的选项，可以在内建变量中直接使用，例如：</p>
<pre><code class="lang-lua">-- 定义一个路径配置选项，默认使用临时目录
option("rootdir")
    set_default("$(tmpdir)")
    set_showmenu(true)

target("test")
    -- 添加指定选项目录中的源文件
    add_files("$(rootdir)/*.c")
</code></pre>
<p>其中，<code>$(rootdir)</code> 就是自定义的选项内建变量，通过手动配置，可以动态修改它的值：</p>
<pre><code class="lang-bash">$ xmake f --rootdir=~/projectdir/src
$ xmake
</code></pre>
<p>给这个<code>rootdir</code>选项指定一个其他的源码目录路径，然后编译。</p>
<p>选项的检测行为：</p>
<table>
<thead>
<tr>
<th>default值</th>
<th>检测行为</th>
</tr>
</thead>
<tbody>
<tr>
<td>没有设置</td>
<td>优先手动配置修改，默认禁用，否则会启用自动检测，也会执行 on_check，可根据手动传入的值类型，自动切换boolean和string类型</td>
</tr>
<tr>
<td>false</td>
<td>开关选项，不自动检测，默认禁用，可手动配置修改</td>
</tr>
<tr>
<td>true</td>
<td>开关选项，不自动检测，默认启用，可手动配置修改</td>
</tr>
<tr>
<td>string类型</td>
<td>无开关状态，不自动检测，可手动配置修改，一般用于配置变量传递</td>
</tr>
</tbody>
</table>
<h3 id="optionset_showmenu">option:set_showmenu</h3>
<h4 id="">设置是否启用菜单显示</h4>
<p>如果设置为<code>true</code>，那么在<code>xmake f --help</code>里面就会出现这个选项，也就能通过<code>xmake f --optionname=xxx</code>进行配置，否则只能在<code>xmake.lua</code>内部使用，无法手动配置修改。</p>
<pre><code class="lang-lua">option("test")
    set_showmenu(true)
</code></pre>
<p>设置为启用菜单后，执行<code>xmake f --help</code>可以看到，帮助菜单里面多了一项：</p>
<pre><code>Options:
    ...

    --test=TEST
</code></pre><h3 id="optionset_category">option:set_category</h3>
<h4 id="">设置选项分类，仅用于菜单显示</h4>
<p>这个是个可选配置，仅用于在帮助菜单中，进行分类显示选项，同一类别的选项，会在同一个分组里面显示，这样菜单看起来更加的美观。</p>
<p>例如：</p>
<pre><code class="lang-lua">option("test1")
    set_showmenu(true)
    set_category("test")

option("test2")
    set_showmenu(true)
    set_category("test")

option("demo1")
    set_showmenu(true)
    set_category("demo")

option("demo2")
    set_showmenu(true)
    set_category("demo")
</code></pre>
<p>这里四个选项分别归类于两个分组：<code>test</code>和<code>demo</code>，那么显示的布局类似这样：</p>
<pre><code class="lang-bash">Options:
    ...

    --test1=TEST1
    --test2=TEST2

    --demo1=DEMO1
    --demo2=DEMO2
</code></pre>
<p>这个接口，仅仅是为了调整显示布局，更加美观而已，没其他用途。</p>
<p>在2.1.9版本中，可以通过category设置分级路径名<code>set_category("root/submenu/submenu2")</code>，来配置<code>xmake f --menu</code>的图形菜单界面，例如：</p>
<pre><code class="lang-lua">-- &#39;boolean&#39; option
option("test1")
    set_default(true)
    set_showmenu(true)
    set_category("root menu/test1")

-- &#39;choice&#39; option with values: "a", "b", "c"
option("test2")
    set_default("a")
    set_values("a", "b", "c")
    set_showmenu(true)
    set_category("root menu/test2")

-- &#39;string&#39; option
option("test3")
    set_default("xx")
    set_showmenu(true)
    set_category("root menu/test3/test3")

-- &#39;number&#39; option
option("test4")
    set_default(6)
    set_showmenu(true)
    set_category("root menu/test4")
</code></pre>
<p>上述配置最后显示的菜单界面路径结构：</p>
<ul>
<li>root menu<ul>
<li>test1</li>
<li>test2</li>
<li>test3<ul>
<li>test3</li>
</ul>
</li>
<li>test4</li>
</ul>
</li>
</ul>
<p>效果图如下：</p>
<p><img src="/assets/img/manual/option_set_category.gif" width="60%" /></p>
<h3 id="optionset_description">option:set_description</h3>
<h4 id="">设置菜单显示描述</h4>
<p>设置选项菜单显示时，右边的描述信息，用于帮助用户更加清楚的知道这个选项的用途，例如：</p>
<pre><code class="lang-lua">option("test")
    set_default(false)
    set_showmenu(true)
    set_description("Enable or disable test")
</code></pre>
<p>生成的菜单内容如下：</p>
<pre><code>Options:
    ...

    --test=TEST                       Enable or disable test (default: false)
</code></pre><p>这个接口也支持多行显示，输出更加详细的描述信息，例如：</p>
<pre><code class="lang-lua">option("mode")
    set_default("debug")
    set_showmenu(true)
    set_description("Set build mode",
                    "    - debug",
                    "    - release",
                    "    - profile")
</code></pre>
<p>生成的菜单内容如下：</p>
<pre><code>Options:
    ...

    --mode=MODE                       Set build mode (default: debug)
                                          - debug
                                          - release
                                          - profile
</code></pre><p>看到这个菜单，用户就能清楚地知道，定义的这个<code>mode</code>选项的具体用处，以及如何使用了：</p>
<pre><code class="lang-bash">$ xmake f --mode=release
</code></pre>
<h3 id="optionadd_links">option:add_links</h3>
<h4 id="">添加链接库检测</h4>
<p>如果指定的链接库检测通过，此选项将被启用，并且对应关联的target会自动加上此链接，例如：</p>
<pre><code class="lang-lua">option("pthread")
    set_default(false)
    add_links("pthread")
    add_linkdirs("/usr/local/lib")

target("test")
    add_options("pthread")
</code></pre>
<p>如果检测通过，<code>test</code>目标编译的时候就会自动加上：<code>-L/usr/local/lib -lpthread</code> 编译选项</p>
<h3 id="optionadd_linkdirs">option:add_linkdirs</h3>
<h4 id="">添加链接库检测时候需要的搜索目录</h4>
<p>这个是可选的，一般系统库不需要加这个，也能检测通过，如果确实没找到，可以自己追加搜索目录，提高检测通过率。具体使用见：<a href="#optionadd_links">add_links</a></p>
<h3 id="optionadd_rpathdirs">option:add_rpathdirs</h3>
<h4 id="">添加程序运行时动态库的加载搜索目录</h4>
<p>在选项通过检测后，会自动添加到对应的target上去，具体使用见：<a href="/mirror/zh-cn/manual/project_target.html#targetadd_rpathdirs">target.add_rpathdirs</a>。</p>
<h3 id="optionadd_cincludes">option:add_cincludes</h3>
<h4 id="c">添加c头文件检测</h4>
<p>如果c头文件检测通过，此选项将被启用，例如：</p>
<pre><code class="lang-lua">option("pthread")
    set_default(false)
    add_cincludes("pthread.h")
    add_defines("ENABLE_PTHREAD")

target("test")
    add_options("pthread")
</code></pre>
<p>此选项检测是否存在<code>pthread.h</code>的头文件，如果检测通过那么<code>test</code>目标程序将会加上<code>ENABLE_PTHREAD</code>的宏定义。</p>
<p>如果想要更加灵活的检测，可以通过<a href="#detect-has_cincludes">lib.detect.has_cincludes</a>在<a href="#optionon_check">option.on_check</a>中去实现。</p>
<h3 id="optionadd_cxxincludes">option:add_cxxincludes</h3>
<h4 id="c">添加c++头文件检测</h4>
<p>与<a href="#optionadd_cincludes">add_cincludes</a>类似，只是检测的头文件类型是c++头文件。</p>
<h3 id="optionadd_ctypes">option:add_ctypes</h3>
<h4 id="c">添加c类型检测</h4>
<p>如果c类型检测通过，此选项将被启用，例如：</p>
<pre><code class="lang-lua">option("wchar")
    set_default(false)
    add_ctypes("wchar_t")
    add_defines("HAVE_WCHAR")

target("test")
    add_options("wchar")
</code></pre>
<p>此选项检测是否存在<code>wchar_t</code>的类型，如果检测通过那么<code>test</code>目标程序将会加上<code>HAVE_WCHAR</code>的宏定义。</p>
<p>如果想要更加灵活的检测，可以通过<a href="#detect-has_ctypes">lib.detect.has_ctypes</a>在<a href="#optionon_check">option.on_check</a>中去实现。</p>
<h3 id="optionadd_cxxtypes">option:add_cxxtypes</h3>
<h4 id="c">添加c++类型检测</h4>
<p>与<a href="#optionadd_ctypes">add_ctypes</a>类似，只是检测的类型是c++类型。</p>
<h3 id="optionadd_csnippets">option:add_csnippets</h3>
<h4 id="c">添加c代码片段检测</h4>
<p>如果现有的<a href="#optionadd_ctypes">add_ctypes</a>, <a href="#optionadd_cfuncs">add_cfuncs</a>等不能满足当前的检测需求，<br>可以用这个接口实现更加定制化检测一些编译器特性检测，具体见: <a href="#optionadd_cxxsnippets">add_cxxsnippets</a>。</p>
<h3 id="optionadd_cxxsnippets">option:add_cxxsnippets</h3>
<h4 id="c">添加c++代码片段检测</h4>
<p>可以用这个接口实现更加定制化检测一些编译器特性检测，尤其是c++的各种特性的检测支持，例如：</p>
<pre><code class="lang-lua">option("constexpr")
    add_cxxsnippets("constexpr", "constexpr int f(int x) { int sum=0; for (int i=0; i<=x; ++i) sum += i; return sum; } constexpr int x = f(5);  static_assert(x == 15);")
</code></pre>
<p>第一个参数设置代码片段的名字作为标示，检测输出信息时候会有显示。</p>
<p>上述代码，实现对c++的constexpr特性的检测，如果检测通过，则启用constexpr选项，当然这里只是个例子。</p>
<p>对于编译器特性的检测，有更加方便高效的检测模块，提供更强大的检测支持，具体见：<a href="#compiler-has_features">compiler.has_features</a>和<a href="#detect-check_cxsnippets">detect.check_cxsnippets</a></p>
<p>如果想要更加灵活的检测，可以通过<a href="#detect-check_cxsnippets">lib.detect.check_cxsnippets</a>在<a href="#optionon_check">option.on_check</a>中去实现。</p>
<p>v2.5.7 版本后，新增 <code>{tryrun = true}</code> 和 <code>{output = true}</code> 两个选项用于尝试运行检测和捕获输出。</p>
<p>设置 tryrun 可以尝试运行来检测：</p>
<pre><code class="lang-lua">option("test")
    add_cxxsnippets("HAS_INT_4", "return (sizeof(int) == 4)? 0 : -1;", {tryrun = true})
</code></pre>
<p>设置 output 也会尝试去检测，并且额外捕获运行的输出内容。</p>
<pre><code class="lang-lua">option("test")
    add_cxxsnippets("INT_SIZE", &#39;printf("%d", sizeof(int)); return 0;&#39;, {output = true, number = true})
</code></pre>
<p>!> 设置为捕获输出，当前 option 不能再设置其他 snippets</p>
<p>我们也可以通过 <code>is_config</code> 获取绑定到option的输出。</p>
<pre><code class="lang-lua">if is_config("test", "8") tben
    -- xxx
end
</code></pre>
<h3 id="optionadd_cfuncs">option:add_cfuncs</h3>
<h4 id="c">添加c库函数检测</h4>
<pre><code class="lang-lua">option("setjmp")
    set_default(false)
    add_cincludes("setjmp.h")
    add_cfuncs("sigsetjmp", "setjmp")
    add_defines("HAVE_SETJMP")

target("test")
    add_options("setjmp")
</code></pre>
<p>此选项检测是否存在<code>setjmp</code>的一些接口，如果检测通过那么<code>test</code> 目标程序将会加上 <code>HAVE_SETJMP</code> 的宏定义。</p>
<p>里面的函数片段支持下面几种语法格式：</p>
<pre><code class="lang-lua">-- 单纯检测函数地址是否存在，内部会尝试去它的地址来判断
sigsetjmp

-- 如果有些函数是宏定义 wrap 的，可以通过这种方式绕通过检测
sigsetjmp((void*)0, 0)

-- 也可以指定一个完整函数语句，例如：funcname{codebody}
sigsetjmp{sigsetjmp((void*)0, 0);}
sigsetjmp{int a = 0; sigsetjmp((void*)a, a);}
</code></pre>
<p>注意，检测的函数通常需要附带 <code>add_cincludes</code> 确保函数能够被正常 include 进来，否则检测会失败。</p>
<h3 id="optionadd_cxxfuncs">option:add_cxxfuncs</h3>
<h4 id="c">添加c++库函数检测</h4>
<p>用法跟 <a href="#optionadd_cxxfuncs">option:add_cfuncs</a> 一致。</p>
</article>
</body>
</html>